#include "desktop.h"
#include "desktop_data.h"
#include "desktop_udp_data.h"

#include <unistd.h>
#include <sys/types.h>  /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#define __USE_MISC 1
#include <net/if.h>
#include <arpa/inet.h>    /* inet(3) functions */
#include <sys/epoll.h>    /* epoll function */
#include <fcntl.h>        /* nonblocking */
#include <sys/resource.h> /*setrlimit */
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>

void desktop_udp_run(cfg_pu_t *pu)
{
    char send_buf[256];
    char recv_buf[256];
    int nread = 0;
    const uint8_t mac_ff[14] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    uint8_t i = 0, AnCount = 0;
    uint32_t crc16 = 0, SendCount = 0;
    uint32_t getCRC = 0;
    int num = 0;
    int tmpIp[4] = {0};
    char macAddr[6];
    char IpStr[32];

    // cfg_pu_t *pu = (cfg_pu_t *)param;
    cfg_enet_t *tcp = (cfg_enet_t *)pu->port.setting;

    // 1 创建一个套接字，用于网络通信
    int sk_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sk_fd == -1)
    {
        UTIL_LOG_E(pu, "can't create socket file");
        pthread_exit(NULL);
    }

    // 2 绑定服务的IP与端口
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(60002);
    int ret = bind(sk_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    if (ret == -1)
    {
        UTIL_LOG_E(pu, "bind desktop_udp error,%s", strerror(errno));
        pthread_exit(NULL);
    }
    // 3 等待 服务器广播
    struct sockaddr_in src_addr;
    socklen_t size = sizeof(servaddr);
    UTIL_LOG_I(pu, "wait broadcast");
    while (1)
    {
        memset(recv_buf, 0, sizeof(recv_buf));
        memset(send_buf, 0, sizeof(send_buf));
        SendCount = 0;
        nread = recvfrom(sk_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&src_addr, &size);
        if (nread == -1)
        {
            UTIL_LOG_E(pu, "recv from desktop_udp error,%s", strerror(errno));
            pthread_exit(NULL);
        }
        printf("desktop udp recv:");
        util_hex_print(recv_buf, nread);
        getCRC = word2Int(recv_buf + nread - 2);
        if (util_crc16(recv_buf, nread - 2) != getCRC)
        {
            printf("get crc error");
            continue;
        }

        if (memcmp(recv_buf, mac_ff, 14) == 0 && recv_buf[14] == 0x03)
        {
            for (i = 0; i < 14; i++)
            {
                send_buf[SendCount++] = 0xff;
            }

            send_buf[SendCount++] = 0x03;
            for (i = 0; i < 14; i++)
            {
                send_buf[SendCount++] = g_cfg->g_basic->product[i];
            }

            int ipInt = inet_addr(g_cfg->g_basic->ip);
            int ip[4] = {0};
            ip[0] = ipInt & 0x000000ff;
            ip[1] = (ipInt & 0xff00) >> 8;
            ip[2] = (ipInt & 0xff0000) >> 16;
            ip[3] = (ipInt & 0xff000000) >> 24;
            for (i = 0; i < 4; i++)
            {
                send_buf[SendCount++] = ip[i];
            }
            ipInt = inet_addr(g_cfg->g_basic->mask);
            ip[0] = ipInt & 0x000000ff;
            ip[1] = (ipInt & 0xff00) >> 8;
            ip[2] = (ipInt & 0xff0000) >> 16;
            ip[3] = (ipInt & 0xff000000) >> 24;
            for (i = 0; i < 4; i++)
            {
                send_buf[SendCount++] = ip[i];
            }
            ipInt = inet_addr(g_cfg->g_basic->gateway);
            ip[0] = ipInt & 0x000000ff;
            ip[1] = (ipInt & 0xff00) >> 8;
            ip[2] = (ipInt & 0xff0000) >> 16;
            ip[3] = (ipInt & 0xff000000) >> 24;
            for (i = 0; i < 4; i++)
            {
                send_buf[SendCount++] = ip[i];
            }

            char macAddr[6];
            if (get_local_mac("eth0", macAddr) < 0)
            {
                for (i = 0; i < 6; i++)
                {
                    send_buf[SendCount++] = 0x00;
                }
            }
            else
            {
                for (i = 0; i < 6; i++)
                {
                    send_buf[SendCount++] = macAddr[i];
                }
            }

            send_buf[SendCount++] = 0x00;

            crc16 = util_crc16(send_buf, SendCount);
            send_buf[SendCount++] = crc16;
            send_buf[SendCount++] = crc16 >> 8;

            ret = sendto(sk_fd, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&src_addr, size);
            if (ret == -1)
            {
                UTIL_LOG_E(pu, "send to desktop_udp error,%s", strerror(errno));
                pthread_exit(NULL);
            }
            util_hex_print(send_buf, SendCount);
        }
        if (memcmp(recv_buf, g_cfg->g_basic->product, 14) == 0 && recv_buf[14] == 0x10)
        {
            // uint8_t dhcp = 0;

            // for (i = 0; i < 14; i++)
            // {
            //     send_buf[SendCount++] = g_cfg->g_basic->product[i];
            // }

            // send_buf[SendCount++] = 0x10;

            // crc16 = util_crc16(send_buf, SendCount);
            // send_buf[SendCount++] = crc16;
            // send_buf[SendCount++] = crc16 >> 8;

            // ret = sendto(sk_fd, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&src_addr, size);
            // if (ret == -1)
            // {
            //     UTIL_LOG_E(pu, "send to desktop_udp error,%s", strerror(errno));
            //     pthread_exit(NULL);
            // }
            // util_hex_print(send_buf, SendCount);
            // // cJSON *basic = cJSON_GetObjectItem(g_cfg->dcfg, "basic");
            // cJSON *basic = cJSON_GetObjectItem(g_cfg->dcfg, "basic");
            // cJSON *ipconfig = cJSON_GetObjectItem(basic, "IP");
            // cJSON *ipNode = cJSON_Duplicate(ipconfig, cJSON_True);

            // AnCount = 15;
            // for (i = 0; i < 4; ++i)
            // {
            //     num = recv_buf[AnCount + i];
            //     if (num < 0)
            //         num += 256;
            //     tmpIp[i] = num;
            // }
            // memset(IpStr, 0, sizeof(IpStr));
            // sprintf(IpStr, "%d.%d.%d.%d", tmpIp[0], tmpIp[1], tmpIp[2], tmpIp[3]);
            // cJSON_ReplaceItemInObject(ipNode, "IP0", cJSON_CreateString(IpStr));

            // AnCount += 4;
            // for (i = 0; i < 4; ++i)
            // {
            //     num = recv_buf[AnCount + i];
            //     if (num < 0)
            //         num += 256;
            //     tmpIp[i] = num;
            // }
            // memset(IpStr, 0, sizeof(IpStr));
            // sprintf(IpStr, "%d.%d.%d.%d", tmpIp[0], tmpIp[1], tmpIp[2], tmpIp[3]);
            // cJSON_ReplaceItemInObject(ipNode, "SUB0", cJSON_CreateString(IpStr));

            // AnCount += 4;
            // for (i = 0; i < 4; ++i)
            // {
            //     num = recv_buf[AnCount + i];
            //     if (num < 0)
            //         num += 256;
            //     tmpIp[i] = num;
            // }
            // memset(IpStr, 0, sizeof(IpStr));
            // sprintf(IpStr, "%d.%d.%d.%d", tmpIp[0], tmpIp[1], tmpIp[2], tmpIp[3]);
            // cJSON_ReplaceItemInObject(ipNode, "GW0", cJSON_CreateString(IpStr));

            // cJSON_DeleteItemFromObject(basic, "IP");
            // ipconfig = NULL;
            // cJSON_AddItemToObject(basic, "IP", ipNode);

            // char *str = cJSON_Print(basic);
            // printf("%s\n", str);
            // cJSON *request = cJSON_Parse(str);
            // if (request == NULL)
            // {
            //     const char *error_ptr = cJSON_GetErrorPtr();
            //     if (error_ptr != NULL)
            //     {
            //         UTIL_LOG_E(pu, "desktop_udp error, %s", strerror(errno));
            //     }
            //     continue;
            // }
            // FILE *file = fopen("./cfg/dtu.json", "w+");
            // char *dtu = cJSON_Print(g_cfg->dcfg);
            // fwrite(dtu, 1, strlen(dtu), file);
            // fclose(file);
            // free(dtu);
            // AnCount += 4;

            // for (i = 0; i < 6; ++i)
            // {
            //     macAddr[i] = recv_buf[AnCount + i];
            // }
            // set_local_mac("eth0", macAddr);
            // // AnCount += 6;
            // // dhcp = BroadData.Buf[AnCount];
        }
    }

    // 4 关闭套接字
    close(sk_fd);
    pthread_exit(NULL);
}


